Another part of my experiments with GTK4 and Haskell was to investigate printing. That brought in the Cairo, Pango and PangoCairo C libraries, and the gi-cairo
, gi-cairo-render
, gi-cairo-connector
, gi-pango
, and gi-pangocairo
Haskell packages.
PrintOperation
At the heart was to create a value of type PrintOperation
, specifying its nPages
and unit
attributes and its handler of the drawPage
signal, and use its run
method with PrintOperationActionPrintDialog
:
1 2 3 4 5 6 7 8 9 |
let onPrintButtonClicked :: IO () onPrintButtonClicked = do printOperation <- Gtk.new Gtk.PrintOperation [ #nPages := 1 , #unit := Gtk.UnitPoints , On #drawPage onDrawPage ] void $ #run printOperation Gtk.PrintOperationActionPrintDialog (Just window) |
renderWithContext
PrintOperationDrawPageCallback
is a type synonym for PrintContext -> Int32 -> IO ()
, and overloaded method getCairoContext
yields a value of type GI.Cairo.Structs.Context.Context
(package gi-cairo
). However, package gi-cairo-render
provides no function to render to a Context
. The solution is package gi-cairo-connector
, which provides renderWithContext
to bridge the gap.
1 2 3 4 |
let onDrawPage :: Gtk.PrintOperationDrawPageCallback onDrawPage printContext _pageNr = do context <- #getCairoContext printContext Cairo.renderWithContext exampleRender context |
exampleRender
Cairo has basic text functionality and Pango provides complex text functionality. My exampleRender
used both:
1 2 3 4 5 6 7 8 9 10 11 12 |
exampleRender :: Cairo.Render () exampleRender = do Cairo.moveTo 72 72 Cairo.setFontSize 10 Cairo.showText ("Hello, Printer!" :: Text) Cairo.moveTo 72 144 Cairo.toRender $ \context -> do layout <- Pango.createLayout context #setText layout "Hello, Printer!" (-1) fontDescription <- Pango.fontDescriptionFromString "Cambria 14" #setFontDescription layout (Just fontDescription) Pango.showLayout context layout |
The Cario origin is the top left corner of the printable area. The printable area excludes the margins specified by the PageSetup
.
Cairo’s showText
renders text so that, by default, it is left-aligned and baseline-aligned.
Package gi-cairo-connector
also provides toRender
with type (GI.Cairo.Context -> IO ()) -> Render ()
.
Pango’s showLayout
renders text so that the top-left corner of the Layout
corresponds to the current point.